﻿using System;
using System.Configuration;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading.Tasks.Dataflow;
using GimmeRainbow.Abstract;
using GimmeRainbow.Concrete;
using GimmeRainbow.Properties;

namespace GimmeRainbow
{
    public partial class MainForm : Form
    {
        static CancellationTokenSource _cancellationSource = new CancellationTokenSource();

        // the batch block to process the files, in the batch of of 1000 items
        static BatchBlock<int> _batchBlock; // The second, and final, node in the dataflow pipeline.
        
        // the action block that calcs the hashes

        // Increments the value of the provided progress bar.
        static ActionBlock<ToolStripProgressBar> _incrementProgress;

        // Enables progress bar actions to run on the UI thread.
        static TaskScheduler _uiTaskScheduler;

        public MainForm()
        {
            InitializeComponent();
            _uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
        }

        private void MainFormLoad(object sender, EventArgs e)
        {
            ResetForm();
        }

        protected void ResetForm()
        {
            # region ActionGrp

            radCreateRainbows.Checked = true;
            radHashFiles.Checked = false;

            # endregion

            # region Files

            txtDictionaryFile.Text = "";
            txtSaltFile.Text = "";
            lstFilesToHash.Items.Clear();

            # endregion

            # region Buttons

            btnAddFile.Enabled = true;
            btnRemoveFile.Enabled = false;
            btnOptions.Enabled = true;
            btnStart.Enabled = false;
            btnPause.Enabled = false;
            btnCancel.Enabled = false;
            

            # endregion
        }

        private void TxtDictionaryFileMouseDown(object sender, MouseEventArgs e)
        {
            HelperClass.SetFileInTextBox(txtDictionaryFile);
            EnableButtons();
        }

        private void EnableButtons()
        {
            if ((txtDictionaryFile.Text != string.Empty && txtSaltFile.Text != string.Empty) || (lstFilesToHash.Items.Count != 0))
                btnStart.Enabled = true;
            else
                btnStart.Enabled = false;
            
        }

        private void TxtSaltFileMouseDown(object sender, MouseEventArgs e)
        {
            HelperClass.SetFileInTextBox(txtSaltFile);
            EnableButtons();
        }

        private void BtnAddFileClick(object sender, EventArgs e)
        {
            using (var openFileDialog = new OpenFileDialog
                                            {
                                                CheckFileExists = true,
                                                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                                                Filter = Resources.MainForm_ListBox_FileFilters
                                            })
            {
                if (openFileDialog.ShowDialog() != DialogResult.OK)
                    return;

                lstFilesToHash.Items.Add(openFileDialog.FileName);
                if (!btnRemoveFile.Enabled)
                    btnRemoveFile.Enabled = true;
            }
            EnableButtons();
        }

        private void BtnRemoveFileClick(object sender, EventArgs e)
        {
            if (lstFilesToHash.SelectedIndex == -1)
                return;

            lstFilesToHash.Items.RemoveAt(lstFilesToHash.SelectedIndex);
            btnRemoveFile.Enabled = lstFilesToHash.Items.Count != 0;
            EnableButtons();
        }

        private void BtnOptionsClick(object sender, EventArgs e)
        {
            using (var configForm = new ConfigurationForm())
            {
                if (configForm.ShowDialog() != DialogResult.OK)
                    return;
            }
            EnableButtons();
        }

       private void BtnStartClick(object sender, EventArgs e)
        {
            if (!ValidatePage())
                return;

            StartHashingAsync();
            
        }

        protected bool ValidatePage()
        {
            return (txtDictionaryFile.Text != string.Empty && txtSaltFile.Text != string.Empty) || (lstFilesToHash.Items.Count != 0);
        }

        async void StartHashingAsync()
        {
            try
            {
                // BAD CODE, DI
                var hasherAsync = new HasherAsync();
                var saltedHasher = new SaltedHasher();

                // Find the action
                if (radCreateRainbows.Checked)
                {
                    // we are creating rainbows, open the files

                    await Task.Run(() => saltedHasher.GenerateSaltedHashAsync(txtDictionaryFile.Text, txtSaltFile.Text,
                                                                        (HelperClass.HashType)
                                                                        Enum.Parse(typeof (HelperClass.HashType),
                                                                                   ConfigurationManager.
                                                                                       AppSettings["HashType"]), _cancellationSource.Token, _uiTaskScheduler));
                    return;
                }
                else
                {

                }
            }
            catch(Exception ex)
            {
                // to do, log the eror and throw
                File.AppendAllText(Path.Combine(Application.StartupPath, "GimmeRainbow.Error.log"),
                                    Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace);
                throw;
            }
        }
    }
}
